package com.csust.automaticteach.controller;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.dashscope.aigc.imagesynthesis.ImageSynthesisResult;
import com.alibaba.dashscope.aigc.videosynthesis.VideoSynthesisResult;
import com.csust.automaticteach.app.teacher.multimodal.PictureGenerateApp;
import com.csust.automaticteach.app.teacher.multimodal.VideoGenerateApp;
import com.csust.automaticteach.common.BaseResponse;
import com.csust.automaticteach.common.ResultUtils;
import com.csust.automaticteach.exception.BusinessException;
import com.csust.automaticteach.exception.ErrorCode;
import com.csust.automaticteach.exception.ThrowUtils;
import com.csust.automaticteach.model.dto.multimodalgen.GenPictureRequest;
import com.csust.automaticteach.model.dto.multimodalgen.GenVideoRequest;
import com.csust.automaticteach.service.MindMapService;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.http.codec.ServerSentEvent;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.io.File;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * ClassName  MultiModalGenController
 * Description  多模态生成控制器
 * Author  钰玟
 * Date 2025/8/5 下午8:32
 * Version 1.0
 **/
@RestController
@RequestMapping("/multi_modal")
public class MultiModalGenController {
    private static final Logger log = LoggerFactory.getLogger(MultiModalGenController.class);
    @Resource
    private PictureGenerateApp pictureGenerateApp;
    @Resource
    private VideoGenerateApp videoGenerateApp;
    @Resource
    private MindMapService mindMapService;
    /**
     * 文生图
     *
     * @param genPictureRequest 请求参数
     * @return 图片结果
     */
    @PostMapping("/gen/text/picture")
    public BaseResponse<List<String>> genPictureByText(@RequestBody GenPictureRequest genPictureRequest) {
        //异步调用
        ImageSynthesisResult imageSynthesisResult = pictureGenerateApp.asyncCall(genPictureRequest);
        // 获取图片结果url
        List<String> urlList = imageSynthesisResult
                .getOutput()
                .getResults()
                .stream()
                .map(result -> result.get("url")).toList();
        //返回图片结果
        return ResultUtils.success(urlList);
    }

    /**
     * 文生视频
     *
     * @param genVideoRequest 请求参数
     * @return 视频结果
     */
    @PostMapping("/gen/text/video")
    public BaseResponse<String> genVideoByText(@RequestBody GenVideoRequest genVideoRequest) {
        VideoSynthesisResult videoSynthesisResult = null;
        try {
            videoSynthesisResult = videoGenerateApp.text2Video(genVideoRequest);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        String videoUrl = videoSynthesisResult.getOutput().getVideoUrl();
        return ResultUtils.success(videoUrl);
    }

    /**
     * 图生视频
     *
     * @param genVideoRequest 请求参数
     * @return 视频结果
     */
    @PostMapping("/gen/picture/video")
    public BaseResponse<String> genVideoByImg(@RequestBody GenVideoRequest genVideoRequest) {
        VideoSynthesisResult videoSynthesisResult = null;
        try {
            videoSynthesisResult = videoGenerateApp.image2video(genVideoRequest);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        String videoUrl = videoSynthesisResult.getOutput().getVideoUrl();
        return ResultUtils.success(videoUrl);
    }

    /**
     * 上传 图片文件
     *
     * @param file 图片文件
     * @return 图片上传结果的绝对路径
     */
    @PostMapping("/gen/picture/upload")
    public BaseResponse<String> genImgUrlByUpload(@RequestParam("file") MultipartFile file) {
        //参数校验
        ThrowUtils.throwIf(file.isEmpty(), ErrorCode.PARAMS_ERROR);
        try {
            // 1. 生成文件保存目录：项目根目录/tmp/gen
            String rootPath = System.getProperty("user.dir"); // 项目根目录
            File saveDir = new File(rootPath, "tmp/gen");
            if (!saveDir.exists()) {
                FileUtil.mkdir(saveDir); // Hutool 创建目录
            }

            // 2. 生成新的文件名（原后缀 + 随机雪花）
            String originalFilename = file.getOriginalFilename();
            String suffix = FileUtil.getSuffix(originalFilename); // Hutool 获取后缀
            String fileName = IdUtil.fastSimpleUUID() + "." + suffix;
            // 3. 保存文件
            File targetFile = new File(saveDir, fileName);
            FileUtil.writeFromStream(file.getInputStream(), targetFile); // Hutool 写入
            // 4. 返回绝对路径
            String absolutePath = targetFile.getAbsolutePath();
            return ResultUtils.success(absolutePath);
        } catch (Exception e) {
            log.error("文件保存失败", e);
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "上传失败");
        }
    }

    /**
     * 删除已上传的文件
     *
     * @param imgUrl 文件的绝对路径
     * @return 删除结果
     */
    @PostMapping("/delete/pic")
    public BaseResponse<Boolean> deletePic(@RequestParam("imgUrl") String imgUrl) {
        if (imgUrl == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        Boolean deleted = videoGenerateApp.deleteFile(imgUrl);
        ThrowUtils.throwIf(!deleted, ErrorCode.SYSTEM_ERROR, "删除失败");
        return ResultUtils.success(true);
    }

    /**
     * 流式生成思维导图
     * @param prompt 用户提示词
     * @return 思维导图结果
     */
    @GetMapping(value = "/gen/mind_map/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<ServerSentEvent<String>> genMindMapStream(@RequestParam("prompt") String prompt, HttpServletRequest  request) {
        String chatId = UUID.randomUUID().toString();
//        Flux<String> stringFlux = mindMapService.genMindMapTextByZhipu(prompt, chatId,request);
        Flux<String> stringFlux = mindMapService.genMindMapTextBySpark(prompt, chatId,request);
        //进一步处理流式数据
        //1. 空格丢失
        Flux<ServerSentEvent<String>> eventFlux = stringFlux.map(chunk -> {
            // 将内容包装成JSON对象
            Map<String, String> wrapper = Map.of("d", chunk);
            String jsonData = JSONUtil.toJsonStr(wrapper);
            return ServerSentEvent.<String>builder()
                    .data(jsonData)
                    .build();
        }).concatWith(Mono.just(
                //2. 自定义 结束事件 done
                        // 发送结束事件
                        ServerSentEvent.<String>builder()
                                .event("done")
                                .data("")
                                .build()
                ));
        return eventFlux;
    }


}
